package cz.muni.fi.pa165.travelagency.web.frontend;

import com.samaxes.stripes.ejb3.EJBBean;
import cz.muni.fi.pa165.travelagency.api.entities.IPackageTour;
import cz.muni.fi.pa165.travelagency.api.services.IPackageTourService;
import cz.muni.fi.pa165.travelagency.dto.PackageTourDTO;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import javax.ejb.EJB;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.Before;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@UrlBinding("/package-tour/{$event}/{package-tour.id}")
@EJB(name = "ptourService", beanInterface = IPackageTourService.class)
public class PackageTourActionBean implements ActionBean {

    public class Search
    {
        private String destination;
        private int maxPrice;
        private Date dateFrom;
        private Date dateTo;
        private int numberOfPersons;

        public Search() {
        }
        
        public Search(String destination) {
            this.destination = destination;
        }        

        public String getDestination() {
            return destination;
        }

        public void setDestination(String destination) {
            this.destination = destination;
        }

        public int getMaxPrice() {
            return maxPrice;
        }

        public void setMaxPrice(int maxPrice) {
            this.maxPrice = maxPrice;
        }

        public Date getDateFrom() {
            return dateFrom;
        }

        public void setDateFrom(Date dateFrom) {
            this.dateFrom = dateFrom;
        }

        public Date getDateTo() {
            return dateTo;
        }

        public void setDateTo(Date dateTo) {
            this.dateTo = dateTo;
        }

        public int getNumberOfPersons() {
            return numberOfPersons;
        }

        public void setNumberOfPersons(int numberOfPersons) {
            this.numberOfPersons = numberOfPersons;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 23 * hash + Objects.hashCode(this.destination);
            hash = 23 * hash + this.maxPrice;
            hash = 23 * hash + Objects.hashCode(this.dateTo);
            hash = 23 * hash + this.numberOfPersons;
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Search other = (Search) obj;
            if (!Objects.equals(this.destination, other.destination)) {
                return false;
            }
            if (this.maxPrice != other.maxPrice) {
                return false;
            }
            if (!Objects.equals(this.dateFrom, other.dateFrom)) {
                return false;
            }
            if (!Objects.equals(this.dateTo, other.dateTo)) {
                return false;
            }
            if (this.numberOfPersons != other.numberOfPersons) {
                return false;
            }
            return true;
        }
    }
    
    @ValidateNestedProperties(value = {
        @Validate(on = {"search", }, field = "destination"),
        @Validate(on = {"search", }, field = "maxPrice"),
        @Validate(on = {"search", }, field = "dateFrom", mask="[1-9]{1,2}\\.[1-9]{1,2}\\.[0-9]{4}"),
        @Validate(on = {"search", }, field = "dateTo", mask="[1-9]{1,2}\\.[1-9]{1,2}\\.[0-9]{4}"),
        @Validate(on = {"search", }, field = "numberOfPersons")
    })
    private Search search;

    public Search getSearch() {
        return search;
    }

    public void setSearch(Search search) {
        this.search = search;
    }
    
    final static Logger log = LoggerFactory.getLogger(PackageTourActionBean.class);
    private ActionBeanContext context;

    private PackageTourDTO ptour;
    
    private List<IPackageTour> packageTours;
    
    @EJBBean("java:comp/env/ptourService")
    private IPackageTourService service;

    @Override
    public void setContext(ActionBeanContext context) {
        this.context = context;
    }

    @Override
    public ActionBeanContext getContext() {
        return context;
    }
     
    String destination;
    int maxPrice;
    Date dateFrom;
    Date dateTo;
    int numberOfPersons;
    
    @Before(stages = LifecycleStage.BindingAndValidation, on = {"list", "search"})
    public void preloadPackageTours() {
        // set defaults
        destination = "";
        numberOfPersons = 1;
        maxPrice = 1000000;
        SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
        try{
        dateFrom = sdf.parse("1.1.2012"); 
        dateTo = sdf.parse("1.1.2100"); 
        }catch(Exception e){}
        
        String param = context.getRequest().getParameter("search.destination");
        if (param != null && !param.equals("")) {
            destination = param;
        }
        
        param = context.getRequest().getParameter("search.maxPrice");
        if (param != null && !param.equals("") && Integer.valueOf(param) != 0) {
            maxPrice = Integer.valueOf(param);
        }
        
        param = context.getRequest().getParameter("search.numberOfPersons");
        if (param != null && !param.equals("") && Integer.valueOf(param) != 0) {
            numberOfPersons = Integer.valueOf(param);
        }
        
        param = context.getRequest().getParameter("search.dateFrom");
        if (param != null && !param.equals("")) {
            try{
            dateFrom = sdf.parse(param); 
            }catch(Exception e){}
        }
        
        param = context.getRequest().getParameter("search.dateTo");
        if (param != null && !param.equals("")) {
            try{
            dateTo = sdf.parse(param); 
            }catch(Exception e){}
        }
        
        packageTours = service.find(destination, maxPrice, dateFrom, dateTo, numberOfPersons);
    } 
    
    public List<IPackageTour> getPackageTours() {
        return packageTours;
    }

    public PackageTourDTO getPtour() {
        return ptour;
    }
    
    public int getAvailablePlaces() {
        return service.getAvailablePlaces(ptour);
    }

    @DefaultHandler
    public Resolution list() {
        return new ForwardResolution("/frontend/package_tour_list.jsp");
    }

    public Resolution detail() {
        return new ForwardResolution("/frontend/package_tour_detail.jsp");
    }
    
    public Resolution search() {
        return new ForwardResolution("/frontend/package_tour_list.jsp");
    }
    
    @Before(stages = LifecycleStage.BindingAndValidation, on = {"detail"})
    public void loadPackageTourFromDatabase() {
        String id = context.getRequest().getParameter("package-tour.id");
        if (id == null) {
            return;
        }
        ptour = (PackageTourDTO) service.getPackageTour(Long.parseLong(id));
    }
}
